package com.lanyam.travel.base.controller;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.UUID;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.lanyam.travel.base.entity.*;
import com.lanyam.travel.base.service.*;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lanyam.travel.base.entity.vo.OrderGoodsDateVo;
import com.lanyam.travel.base.entity.vo.RefundRecordVo;
import com.lanyam.travel.base.entity.vo.TravelOrderVo;
import com.lanyam.travel.base.exception.NoTicketException;
import com.lanyam.travel.base.utils.Constant;
import com.lanyam.travel.base.utils.JSONResult;
import com.lanyam.travel.base.utils.MD5Utils;
import com.lanyam.travel.base.utils.PayUtil;
import com.lanyam.travel.base.utils.WXCodeUtil;

@RestController
@RequestMapping("order")
public class OrderController {

	Logger logger = Logger.getLogger(OrderController.class);
	
	@Autowired
	private ITravelOrderService travelOrderService;
	
	@Autowired
	private IOrderUserService orderUserService;
	
	@Autowired
	private IGoodsDateService goodsDateService;
	
	@Autowired
	private ITicketTypeService ticketTypeService;
	
	@Autowired
	private IScenicHotelService scenicHotelService;
	
	@Autowired
	private ITravelLineService travelLineService;
	
	@Autowired
	private IGoodsInfoService goodsInfoService;
	
	@Autowired
	private ITravelOrderDetailsService orderDetailsService;
	
	@Autowired
	private IOrderGoodsDateService orderGoodsDateService;

	@Autowired
	private IDistrRecordService distrRecordService;
	
	@Autowired
	private IDistrUserService distrUserService;

	@Autowired
	private ICaseWithdraService caseWithdraService;
	/**
	 * 根据选择的供应商和产品类型获取对应的产品
	 * @param supplierId
	 * @param productType
	 * @return
	 */
	@PostMapping("/getProductBySupplierAndType")
	public JSONResult getProductBySupplierAndType(String supplierId,int productType)
	{
		if(StringUtils.isEmpty(supplierId)||StringUtils.isEmpty(productType+""))
		{
			return JSONResult.errorMsg("参数不全");
		}
		if(productType > 1)
		{
			List<TravelLine> lineList = travelLineService.getProductBySupplier(supplierId);
			return JSONResult.ok(lineList);
		}
		else
		{
			List<ScenicHotel> scenicList = scenicHotelService.getProductBySupplierAndType(supplierId,productType);
			return JSONResult.ok(scenicList);
		}
	}
	/**
	 * 获取供应商下的所有商品
	 * @param supplierId 供应商id
	 * @return
	 */
	@PostMapping("/getProductBySupplier")
	public JSONResult getProductBySupplier(String supplierId)
	{
		List<ScenicHotel> scenicList = scenicHotelService.getProductBySupplier(supplierId);
		List<TravelLine> lineList = travelLineService.getProductBySupplier(supplierId);
		List<Product> allProducts = new ArrayList<Product>();
		allProducts.addAll(scenicList);
		allProducts.addAll(lineList);
		return JSONResult.ok(allProducts);
	}
	/**
	 * 获取线路/景区的门票或酒店的房间类型
	 * @param productId 线路/景区/酒店id
	 * @return
	 */
	@PostMapping("/getGoodsByProductId")
	public JSONResult getGoodsByProductId(String productId)
	{
		if(StringUtils.isEmpty(productId))
		{
			return JSONResult.errorMsg("参数不全");
		}
		Product product = scenicHotelService.getScenicById(productId);
		if(null == product)
		{
			product = travelLineService.getTravelLineById(productId);
		}
		if(null == product)
		{
			return JSONResult.errorMsg("获取商品信息失败");
		}
		if(product.getProductType() == 1)
		{
			List<GoodsInfo> goodsInfoList = goodsInfoService.getGoodsInfoByProductId(productId);
			return JSONResult.ok(goodsInfoList);
		}
		else
		{
			List<ProductTicket> tickeTypeList = ticketTypeService.getTickeTypeByProductId(productId);
			return JSONResult.ok(tickeTypeList);
		}
	}
	/**
	 * 后台创建订单
	 * @param orderVo
	 * @return
	 */
	@PostMapping("/createOrderByAdmin")
	@Transactional(rollbackFor = NoTicketException.class)
	public JSONResult createOrderByAdmin(@RequestBody TravelOrderVo orderVo)
	{
		String orderId = MD5Utils.createOrderId();
		TravelOrder order = new TravelOrder();
		order.setId(orderId);
		order.setOrderType(0);
		order.setProductId(orderVo.getProductId());
		order.setOrderUserid(orderVo.getOrderUserid());//供应商管理员id(默认登陆用户id)
		order.setOrderUsername(orderVo.getOrderUsername());
		order.setOrderTime(new Date());
		order.setOverrdueTime(new Date());//待改
		order.setContact(orderVo.getContact());
		order.setTelephone(orderVo.getTelephone());
		order.setPayStatus(1);
		order.setRemarks(orderVo.getRemarks());
		order.setBookUseDate(orderVo.getBookUseDate());//旅行开始日期，根据前台日历选择,精确到日
		order.setBookEndDate(orderVo.getBookEndDate());//旅行最后一天的日期，根据前提日历选择，精确到日
		order.setTripStatus(0);
		order.setSupplyId(orderVo.getSupplyId());
		//设置订单的分销员
		order.setDistrUserId(orderVo.getDistrUserId());
		//设置订单支付后的随机码
    	String randomCode = MD5Utils.createRandomCode(6);
    	order.setRandomCode(randomCode);
    	if(null == orderVo.getPayAmount() || orderVo.getPayAmount().doubleValue() == 0)
    	{
    		return JSONResult.errorMsg("支付金额不能为0");
    	}
    	BigDecimal payAmount = orderVo.getPayAmount();
    	order.setPayAmount(payAmount);
    	order.setPayTime(new Date());
		String productId = orderVo.getProductId();
		Product product = scenicHotelService.getScenicById(productId);
		if(null == product)
		{
			product = travelLineService.getTravelLineById(productId);
		}
		if(null == product)
		{
			return JSONResult.errorMsg("获取商品信息失败");
		}
		//获取产品类型，0为景区，1为酒店，2为线路
		int productType = product.getProductType();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
		Date bookUserDate = orderVo.getBookUseDate();
		Date bookEndDate = orderVo.getBookEndDate();
		String startDay = sdf.format(bookUserDate);
		String endDay = "";
		if(bookEndDate!=null) {
			endDay = sdf.format(bookEndDate);
		}else{
			endDay = startDay;
			orderVo.setBookEndDate(bookUserDate);
		}
		
		List<OrderUser> orderUserList = orderVo.getOrderUserList();
		if(null != orderUserList && orderUserList.size() > 0)
		{
			for (OrderUser orderUser : orderUserList) {
				orderUser.setId(UUID.randomUUID().toString().replace("-", ""));
				orderUser.setOrderId(orderId);
			}
			orderUserService.batchAddOrderUser(orderUserList);
		}

		List<OrderGoodsDate> datePriceList = new ArrayList<OrderGoodsDate>();
		List<TravelOrderDetails> orderDetailList = orderVo.getOrderDetailList();
		if(productType == 1)
		{
			//酒店，获取酒店房间类型的每日价格，每日房间类型的价格*预定数量，然后所有房间类型总价相加
			//获取指定房间类型在指定日期下的每日价格
			if(null != orderDetailList && orderDetailList.size() > 0)
			{
				for (TravelOrderDetails travelOrderDetail : orderDetailList) 
				{
					//先补全订单详情的信息
					String goodsId = travelOrderDetail.getId();//房间类型id
					String orderDetailId = UUID.randomUUID().toString().replace("-", "");
					travelOrderDetail.setId(orderDetailId);
					travelOrderDetail.setGoodType(product.getProductType());
					travelOrderDetail.setGoodId(goodsId);
					travelOrderDetail.setOrderId(orderId);
					int quality = travelOrderDetail.getGoodQuality();//预定的房间类型的数量
					//设置商品的日期价格
					List<GoodsDate> goodsDateList = goodsDateService.queryGoodsDateInDays(travelOrderDetail.getGoodId(), startDay, endDay);
					for (GoodsDate goodsDate : goodsDateList) 
					{
						if(quality > goodsDate.getRemaindNum())
						{
							GoodsInfo goodsInfo = goodsInfoService.getGoodsInfoById(travelOrderDetail.getGoodId());
							throw new NoTicketException(goodsDate.getTheDate()+"的"+goodsInfo.getGoodName()+"数量不足，创建订单失败");
						}
						OrderGoodsDate datePrice = new OrderGoodsDate();
						datePrice.setOrderId(orderId);
						datePrice.setOrderDetailId(orderDetailId);
						datePrice.setGoodsId(goodsId);
						datePrice.setGoodType(productType);
						datePrice.setTheDate(bookUserDate);
						//设置当天，某个票类型的实际价格(去掉优惠后的价格)
						double price = goodsDate.getPrice();//*(1-ticket.getDiscountRate());
						datePrice.setGoodPrice(new BigDecimal(price));
						datePrice.setGoodQuality(quality);
						datePrice.setDiscountRate(0.0);
						datePrice.setDiscountType(0);
						datePrice.setTicketType(-1);//酒店没有票类型
						datePriceList.add(datePrice);
					}
				}
			}
		}
		else
		{
			//线路/景区，获取当日的门票价格，当日价格*(门票类型的折扣1*数量+门票类型折扣2*数量)，
			//线路/景区指定日期下的每日价格
			GoodsDate scenicDatePrice = goodsDateService.queryByGoodsIdAndDay(productId, bookUserDate);
			if(null != orderDetailList && orderDetailList.size() > 0)
			{
				for (TravelOrderDetails travelOrderDetail: orderDetailList) 
				{
					//good_id，good_quality前台传值
					String goodsId = travelOrderDetail.getId();//票类型id
					String orderDetailId = UUID.randomUUID().toString().replace("-", "");
					travelOrderDetail.setId(orderDetailId);
					travelOrderDetail.setGoodType(productType);
					travelOrderDetail.setGoodId(goodsId);
					travelOrderDetail.setOrderId(orderId);
					//travelOrderDetail赋值结束
					int quality = travelOrderDetail.getGoodQuality();//票类型的数量
					if(quality > scenicDatePrice.getRemaindNum())
					{
						throw new NoTicketException(bookUserDate+"的余票数量不足，订单创建失败。");
					}
					//线路和景区只有一个日期，一个travelOrderDetail对应一条OrderGoodsDate记录
					OrderGoodsDate datePrice = new OrderGoodsDate();
					datePrice.setOrderId(orderId);
					datePrice.setOrderDetailId(orderDetailId);
					datePrice.setGoodsId(goodsId);
					datePrice.setGoodType(product.getProductType());
					datePrice.setTheDate(bookUserDate);
					//设置当天，某个票类型的实际价格(去掉优惠后的价格)
					ProductTicket ticket = ticketTypeService.getProductTicketById(goodsId);
					double price = scenicDatePrice.getPrice();//*(1-ticket.getDiscountRate());
					if(ticket.getDiscountType() == 0)
					{
						price = (1-ticket.getDiscountRate().doubleValue())*price;
					}
					else
					{
						price = price - ticket.getDiscountRate().doubleValue();
					}
					datePrice.setGoodPrice(new BigDecimal(price));
					datePrice.setGoodQuality(quality);
					datePrice.setDiscountRate(ticket.getDiscountRate().doubleValue());
					datePrice.setDiscountType(ticket.getDiscountType());
					datePrice.setTicketType(ticket.getTicketType());
					datePriceList.add(datePrice);
				}
			}
		}
		if(null != orderDetailList && orderDetailList.size() > 0)
		{
			orderDetailsService.batchInsertOrderDetails(orderDetailList);
		}
		double totalFee = 0.0;
		if(datePriceList.size() > 0)
		{
			orderGoodsDateService.batchInsertOrderGoodsDate(datePriceList);
			//设置订单的实际总金额
			for (OrderGoodsDate datePrice : datePriceList) {
				totalFee += datePrice.getGoodPrice().doubleValue() * datePrice.getGoodQuality();
			}
			order.setRealAmount(new BigDecimal(totalFee));
		}
		if(payAmount.doubleValue() != totalFee )
		{
			return JSONResult.errorMsg("支付金额与后台计算金额不一致");
		}
		order.setOrderAmount(new BigDecimal(totalFee));
		
		travelOrderService.addOrder(order);
		//订单创建成功后，产品的交易次数加1
		product.setDealCount(product.getDealCount() + 1);
		if(productType < 2)
		{
			scenicHotelService.update((ScenicHotel) product);
		}
		else
		{
			travelLineService.update((TravelLine) product);
		}
		
		return JSONResult.ok(order);
	}
	/**
	 * 创建订单
	 * @return
	 * @throws InvocationTargetException 
	 * @throws IllegalAccessException 
	 */
	@RequestMapping(value = "/createOrder", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
	@Transactional(rollbackFor = NoTicketException.class)
	public JSONResult creteOrder(@RequestBody TravelOrderVo orderVo) throws IllegalAccessException, InvocationTargetException
	{
		//1.设置订单基本信息并入库：
		//后台赋值：订单类型/创建订单时间/订单总金额/订单实际金额/订单支付状态
		//前台赋值：下单人id/下单人名称/订单联系人/联系人电话/描述/订单预定使用日期/订单预定后的失效时间

		String orderId = MD5Utils.createOrderId();
		TravelOrder order = new TravelOrder();
		order.setId(orderId);
		order.setOrderType(Integer.parseInt(orderVo.getIsPanic()));
		order.setProductId(orderVo.getProductId());
		order.setOrderUserid(orderVo.getOrderUserid());//小程序登陆用户的id
		order.setOrderUsername(orderVo.getOrderUsername());
		order.setOrderTime(new Date());
//		order.setOverrdueTime(overrdueTime);
		order.setContact(orderVo.getContact());
		order.setTelephone(orderVo.getTelephone());
		order.setPayStatus(0);
		order.setOrderAmount(orderVo.getOrderAmount());
		order.setRealAmount(orderVo.getRealAmount());
		order.setRemarks(orderVo.getRemarks());
		order.setBookUseDate(orderVo.getBookUseDate());//旅行开始日期，根据前台日历选择,精确到日
		if(orderVo.getBookEndDate()!=null) {
			order.setBookEndDate(orderVo.getBookEndDate());//旅行最后一天的日期，根据前提日历选择，精确到日
		}else{
			order.setBookEndDate(orderVo.getBookUseDate());
		}
		order.setTripStatus(0);
		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.MINUTE,30);
		order.setOverrdueTime(cal.getTime());//设置订单失效时间

		String productId = orderVo.getProductId();
		Product product = scenicHotelService.getScenicById(productId);
		if(null == product)
		{
			product = travelLineService.getTravelLineById(productId);
		}
		if(null == product)
		{
			return JSONResult.errorMsg("获取商品信息失败");
		}
		order.setSupplyId(product.getSupplyId());

		//获取产品类型，0为景区，1为酒店，2为线路
		int productType = product.getProductType();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
		Date bookUserDate = orderVo.getBookUseDate();
		Date bookEndDate = orderVo.getBookEndDate();
		String startDay = sdf.format(bookUserDate);
		String endDay = "";
		if(bookEndDate!=null) {
			endDay = sdf.format(bookEndDate);
		}else{
			endDay = startDay;
		}
		List<OrderUser> orderUserList = orderVo.getOrderUserList();
		if(null != orderUserList && orderUserList.size() > 0)
		{
			for (OrderUser orderUser : orderUserList) {
				orderUser.setId(UUID.randomUUID().toString().replace("-", ""));
				orderUser.setOrderId(orderId);
			}
			orderUserService.batchAddOrderUser(orderUserList);
		}
		List<OrderGoodsDate> datePriceList = new ArrayList<OrderGoodsDate>();
		List<TravelOrderDetails> orderDetailList = orderVo.getOrderDetailList();
		if(productType == 1)
		{
			//酒店，获取酒店房间类型的每日价格，每日房间类型的价格*预定数量，然后所有房间类型总价相加
			//获取指定房间类型在指定日期下的每日价格
			if(null != orderDetailList && orderDetailList.size() > 0)
			{
				for (TravelOrderDetails travelOrderDetail : orderDetailList)
				{
					//先补全订单详情的信息
					String orderDetailId = UUID.randomUUID().toString().replace("-", "");
					travelOrderDetail.setId(orderDetailId);
					travelOrderDetail.setGoodType(product.getProductType());
					travelOrderDetail.setOrderId(orderId);
					String goodsId = travelOrderDetail.getGoodId();//房间类型id
					int quality = travelOrderDetail.getGoodQuality();//预定的房间类型的数量
					//设置商品的日期价格
					List<GoodsDate> goodsDateList = goodsDateService.queryGoodsDateInDays(travelOrderDetail.getGoodId(), startDay, endDay);
					for (GoodsDate goodsDate : goodsDateList)
					{
						if(quality > goodsDate.getRemaindNum())
						{
							GoodsInfo goodsInfo = goodsInfoService.getGoodsInfoById(travelOrderDetail.getGoodId());
//							throw new NoTicketException(goodsDate.getTheDate()+"的"+goodsInfo.getGoodName()+"数量不足，创建订单失败");
							return JSONResult.errorMsg(sdf.format(goodsDate.getTheDate())+"的"+goodsInfo.getGoodName()+"数量不足，创建订单失败");
						}
						OrderGoodsDate datePrice = new OrderGoodsDate();
						datePrice.setOrderId(orderId);
						datePrice.setOrderDetailId(orderDetailId);
						datePrice.setGoodsId(goodsId);
						datePrice.setGoodType(productType);
						datePrice.setTheDate(bookUserDate);
						//设置当天，某个票类型的实际价格(去掉优惠后的价格)
						double price = goodsDate.getPrice();//*(1-ticket.getDiscountRate());
						datePrice.setGoodPrice(new BigDecimal(price));
						datePrice.setGoodQuality(quality);
						datePrice.setDiscountRate(0.0);
						datePrice.setDiscountType(0);
						datePrice.setTicketType(-1);//酒店没有票类型
						datePriceList.add(datePrice);
					}
				}
			}
		}
		else
		{
			//线路/景区，获取当日的门票价格，当日价格*(门票类型的折扣1*数量+门票类型折扣2*数量)，
			//线路/景区指定日期下的每日价格
			GoodsDate scenicDatePrice = goodsDateService.queryByGoodsIdAndDay(productId, bookUserDate);
			if(null != orderDetailList && orderDetailList.size() > 0)
			{
				for (TravelOrderDetails travelOrderDetail: orderDetailList)
				{
					//good_id，good_quality前台传值
					String orderDetailId = UUID.randomUUID().toString().replace("-", "");
					travelOrderDetail.setId(orderDetailId);
					travelOrderDetail.setGoodType(productType);
					travelOrderDetail.setOrderId(orderId);
					//travelOrderDetail赋值结束
					String goodsId = travelOrderDetail.getGoodId();//票类型id
					int quality = travelOrderDetail.getGoodQuality();//票类型的数量
					if(scenicDatePrice==null || quality > scenicDatePrice.getRemaindNum())
					{
//						throw new NoTicketException(bookUserDate+"的余票数量不足，订单创建失败。");
						return JSONResult.errorMsg(sdf.format(bookUserDate)+"的余票数量不足，创建订单失败");
					}
					//线路和景区只有一个日期，一个travelOrderDetail对应一条OrderGoodsDate记录
					OrderGoodsDate datePrice = new OrderGoodsDate();
					datePrice.setOrderId(orderId);
					datePrice.setOrderDetailId(orderDetailId);
					datePrice.setGoodsId(goodsId);
					datePrice.setGoodType(product.getProductType());
					datePrice.setTheDate(bookUserDate);
					//设置当天，某个票类型的实际价格(去掉优惠后的价格)
					ProductTicket ticket = ticketTypeService.getProductTicketById(goodsId);
					double price = scenicDatePrice.getPrice();//*(1-ticket.getDiscountRate());
					if(ticket.getDiscountType() == 0)
					{
						price = (1-ticket.getDiscountRate().doubleValue())*price;
					}
					else
					{
						price = price - ticket.getDiscountRate().doubleValue();
					}
					datePrice.setGoodPrice(new BigDecimal(price));
					datePrice.setGoodQuality(quality);
					datePrice.setDiscountRate(ticket.getDiscountRate().doubleValue());
					datePrice.setDiscountType(ticket.getDiscountType());
					datePrice.setTicketType(ticket.getTicketType());
					datePriceList.add(datePrice);
				}
			}
		}
		if(null != orderDetailList && orderDetailList.size() > 0)
		{
			orderDetailsService.batchInsertOrderDetails(orderDetailList);
		}
		if(datePriceList.size() > 0)
		{
			orderGoodsDateService.batchInsertOrderGoodsDate(datePriceList);
		}
		travelOrderService.addOrder(order);
		//订单创建成功后，产品的交易次数加1
		int dealCount = null==product.getDealCount()?0:product.getDealCount();
		product.setDealCount(dealCount + 1);
		if(productType < 2)
		{
			scenicHotelService.update((ScenicHotel) product);
		}
		else
		{
			travelLineService.update((TravelLine) product);
		}

		return JSONResult.ok(order);
	}
	
	/**
	 * 订票(抢购之后的预定)
	 * @param orderVo
	 * @return
	 */
	@PostMapping("/bookTicket")
	public JSONResult bookTicket(TravelOrderVo orderVo)
	{
		String orderId = orderVo.getId();
		TravelOrder order = travelOrderService.queryOrderById(orderId);
		order.setOrderType(1);
//		order.setOverrdueTime(overrdueTime);
		order.setContact(orderVo.getContact());
		order.setTelephone(orderVo.getTelephone());
		order.setPayStatus(0);
		order.setOrderAmount(orderVo.getOrderAmount());
		order.setRealAmount(orderVo.getRealAmount());
		order.setRemarks(orderVo.getRemarks());
		order.setBookUseDate(orderVo.getBookUseDate());//旅行开始日期，根据前台日历选择,精确到日
		order.setBookEndDate(orderVo.getBookEndDate());//旅行最后一天的日期，根据前提日历选择，精确到日
		order.setTripStatus(0);
		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.MINUTE,30);
		order.setOverrdueTime(cal.getTime());//设置订单失效时间

		String productId = order.getProductId();
		Product product = scenicHotelService.getScenicById(productId);
		if(null == product)
		{
			product = travelLineService.getTravelLineById(productId);
		}
		if(null == product)
		{
			return JSONResult.errorMsg("获取商品信息失败");
		}
		order.setSupplyId(product.getSupplyId());

		//获取产品类型，0为景区，1为酒店，2为线路
		int productType = product.getProductType();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
		Date bookUserDate = orderVo.getBookUseDate();
		if(bookUserDate==null){
			bookUserDate = new Date();
		}
		Date bookEndDate = orderVo.getBookEndDate();
		String startDay = sdf.format(bookUserDate);
		String endDay = "";
		if(bookEndDate!=null) {
			endDay = sdf.format(bookEndDate);
		}else{
			endDay = startDay;
		}
		List<OrderUser> orderUserList = orderVo.getOrderUserList();
		if(null != orderUserList && orderUserList.size() > 0)
		{
			for (OrderUser orderUser : orderUserList) {
				orderUser.setId(UUID.randomUUID().toString().replace("-", ""));
				orderUser.setOrderId(orderId);
			}
			orderUserService.batchAddOrderUser(orderUserList);
		}
		List<OrderGoodsDate> datePriceList = new ArrayList<OrderGoodsDate>();
		List<TravelOrderDetails> orderDetailList = orderVo.getOrderDetailList();
		if(productType == 1)
		{
			//酒店，获取酒店房间类型的每日价格，每日房间类型的价格*预定数量，然后所有房间类型总价相加
			//获取指定房间类型在指定日期下的每日价格
			if(null != orderDetailList && orderDetailList.size() > 0)
			{
				for (TravelOrderDetails travelOrderDetail : orderDetailList)
				{
					//先补全订单详情的信息
					String orderDetailId = UUID.randomUUID().toString().replace("-", "");
					travelOrderDetail.setId(orderDetailId);
					travelOrderDetail.setGoodType(product.getProductType());
					travelOrderDetail.setOrderId(orderId);
					String goodsId = travelOrderDetail.getGoodId();//房间类型id
					int quality = travelOrderDetail.getGoodQuality();//预定的房间类型的数量
					//设置商品的日期价格
					List<GoodsDate> goodsDateList = goodsDateService.queryGoodsDateInDays(travelOrderDetail.getGoodId(), startDay, endDay);
					for (GoodsDate goodsDate : goodsDateList)
					{
						if(quality > goodsDate.getRemaindNum())
						{
							GoodsInfo goodsInfo = goodsInfoService.getGoodsInfoById(travelOrderDetail.getGoodId());
							throw new NoTicketException(goodsDate.getTheDate()+"的"+goodsInfo.getGoodName()+"数量不足，创建订单失败");
						}
						OrderGoodsDate datePrice = new OrderGoodsDate();
						datePrice.setOrderId(orderId);
						datePrice.setOrderDetailId(orderDetailId);
						datePrice.setGoodsId(goodsId);
						datePrice.setGoodType(productType);
						datePrice.setTheDate(bookUserDate);
						//设置当天，某个票类型的实际价格(去掉优惠后的价格)
						double price = goodsDate.getPrice();//*(1-ticket.getDiscountRate());
						datePrice.setGoodPrice(new BigDecimal(price));
						datePrice.setGoodQuality(quality);
						datePrice.setDiscountRate(0.0);
						datePrice.setDiscountType(0);
						datePrice.setTicketType(-1);//酒店没有票类型
						datePriceList.add(datePrice);
					}
				}
			}
		}
		else
		{
			//线路/景区，获取当日的门票价格，当日价格*(门票类型的折扣1*数量+门票类型折扣2*数量)，
			//线路/景区指定日期下的每日价格
			GoodsDate scenicDatePrice = goodsDateService.queryByGoodsIdAndDay(productId, bookUserDate);
			if(null != orderDetailList && orderDetailList.size() > 0)
			{
				for (TravelOrderDetails travelOrderDetail: orderDetailList)
				{
					//good_id，good_quality前台传值
					String orderDetailId = UUID.randomUUID().toString().replace("-", "");
					travelOrderDetail.setId(orderDetailId);
					travelOrderDetail.setGoodType(productType);
					travelOrderDetail.setOrderId(orderId);
					//travelOrderDetail赋值结束
					String goodsId = travelOrderDetail.getGoodId();//票类型id
					int quality = travelOrderDetail.getGoodQuality();//票类型的数量
					if(scenicDatePrice==null || quality > scenicDatePrice.getRemaindNum())
					{
						throw new NoTicketException(bookUserDate+"的余票数量不足，订单创建失败。");
					}
					//线路和景区只有一个日期，一个travelOrderDetail对应一条OrderGoodsDate记录
					OrderGoodsDate datePrice = new OrderGoodsDate();
					datePrice.setOrderId(orderId);
					datePrice.setOrderDetailId(orderDetailId);
					datePrice.setGoodsId(goodsId);
					datePrice.setGoodType(product.getProductType());
					datePrice.setTheDate(bookUserDate);
					//设置当天，某个票类型的实际价格(去掉优惠后的价格)
					ProductTicket ticket = ticketTypeService.getProductTicketById(goodsId);
					double price = scenicDatePrice.getPrice();//*(1-ticket.getDiscountRate());
					if(ticket.getDiscountType() == 0)
					{
						price = (1-ticket.getDiscountRate().doubleValue())*price;
					}
					else
					{
						price = price - ticket.getDiscountRate().doubleValue();
					}
					datePrice.setGoodPrice(new BigDecimal(price));
					datePrice.setGoodQuality(quality);
					datePrice.setDiscountRate(ticket.getDiscountRate().doubleValue());
					datePrice.setDiscountType(ticket.getDiscountType());
					datePrice.setTicketType(ticket.getTicketType());
					datePriceList.add(datePrice);
				}
			}
		}
		if(null != orderDetailList && orderDetailList.size() > 0)
		{
			orderDetailsService.batchInsertOrderDetails(orderDetailList);
		}
		if(datePriceList.size() > 0)
		{
			orderGoodsDateService.batchInsertOrderGoodsDate(datePriceList);
		}
		travelOrderService.addOrder(order);
		//订单创建成功后，产品的交易次数加1
		product.setDealCount(product.getDealCount() + 1);
		if(productType < 2)
		{
			scenicHotelService.update((ScenicHotel) product);
		}
		else
		{
			travelLineService.update((TravelLine) product);
		}

		return JSONResult.ok();
	}
	
	/**
	 * 订单支付
	 * @return
	 */
	@PostMapping("/wxpay")
	@ResponseBody
	public JSONResult wxpay(String orderId,String openId,HttpServletRequest request)
	{
//		TravelOrder order = travelOrderService.getOrderById(orderId);
//		Product product = travelOrderService.getProductByOrderId(order.get);
		try {
            //生成的随机字符串
            String nonce_str = WXCodeUtil.getRandomStringByLength(32);
            //商品名称
//            String body = product.getName();
            
            //获取客户端的ip地址
            String spbill_create_ip = WXCodeUtil.getIpAddr(request);
            //组装参数，用户生成统一下单接口的签名
            Map<String, String> packageParams = new HashMap<>();
            packageParams.put("appid", Constant.APP_ID);
			packageParams.put("body", "测试支付");
            packageParams.put("mch_id", Constant.MCH_ID);
			packageParams.put("nonce_str", nonce_str);
			packageParams.put("notify_url", Constant.NOTIFY_URL);//支付成功后的回调地址
			packageParams.put("openid", openId);
			packageParams.put("out_trade_no", orderId);//商户订单号,自己的订单ID
			packageParams.put("spbill_create_ip", spbill_create_ip);
			packageParams.put("total_fee", "1");
			packageParams.put("trade_type", Constant.TRADETYPE);//支付方式
            String prestr = PayUtil.createLinkString(packageParams);           // 把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
            String mysign = PayUtil.sign(prestr, Constant.key, "utf-8").toUpperCase(); //MD5运算生成签名，这里是第一次签名，用于调用统一下单接口
            //拼接统一下单接口使用的xml数据，要将上一步生成的签名一起拼接进去
            String xml = "<xml>"
                    + "<appid><![CDATA[" + Constant.APP_ID + "]]></appid>"
                    + "<body><![CDATA[测试支付]]></body>"
                    + "<mch_id><![CDATA[" + Constant.MCH_ID + "]]></mch_id>"
                    + "<nonce_str><![CDATA[" + nonce_str + "]]></nonce_str>"
                    + "<notify_url><![CDATA[" + Constant.NOTIFY_URL + "]]></notify_url>"
                    + "<openid><![CDATA[" + openId + "]]></openid>"
                    + "<out_trade_no><![CDATA[" + orderId + "]]></out_trade_no>"
                    + "<spbill_create_ip><![CDATA[" + spbill_create_ip + "]]></spbill_create_ip>"
                    + "<total_fee><![CDATA[" + 1 + "]]></total_fee>"//支付的金额，单位：分
                    + "<trade_type><![CDATA[" + Constant.TRADETYPE + "]]></trade_type>"
                    + "<sign><![CDATA[" + mysign + "]]></sign>"
                    + "</xml>";
            //调用统一下单接口，并接受返回的结果
            String result = PayUtil.httpRequest(Constant.PAY_URL, "POST", xml);

            // 将解析结果存储在HashMap中
            Map map = PayUtil.doXMLParse(result);

            String return_code = (String) map.get("return_code");//返回状态码
            String result_code = (String) map.get("result_code");//返回状态码
            Map<String, Object> returnResult = new HashMap<String, Object>();//返回给小程序端需要的参数
            if (return_code.equals("SUCCESS")  && return_code.equals(result_code)) {
                String prepay_id = (String) map.get("prepay_id");//返回的预付单信息
                returnResult.put("nonceStr", nonce_str);
                returnResult.put("package", "prepay_id=" + prepay_id);
                Long timeStamp = System.currentTimeMillis() / 1000;
                returnResult.put("timeStamp", timeStamp + "");//这边要将返回的时间戳转化成字符串，不然小程序端调用wx.requestPayment方法会报签名错误
                //拼接签名需要的参数
                String stringSignTemp = "appId=" + Constant.APP_ID + "&nonceStr=" + nonce_str + "&package=prepay_id=" + prepay_id + "&signType=MD5&timeStamp=" + timeStamp;
                //再次签名，这个签名用于小程序端调用wx.requesetPayment方法
                String paySign = PayUtil.sign(stringSignTemp, Constant.key, "utf-8").toUpperCase();

                returnResult.put("paySign", paySign);
            }
			if(return_code.equals("FAIL")){
				return JSONResult.errorMsg("发起支付失败。"+map.get("return_msg"));
			}else {
				returnResult.put("appid", Constant.APP_ID);
				return JSONResult.ok(returnResult);
			}
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("支付失败：" + e.getMessage());
        }
        return JSONResult.errorMsg("发起支付失败。");

//		Map<String,Object> map = travelOrderService.paywxr(request);
//		return JSONResult.ok(map);
	}


	/**
	 * 支付成功后调用
	 * @param orderId
	 * @param openId
	 * @return
	 */
	@PostMapping("/paySuccess")
	@ResponseBody
	@Transactional(rollbackFor = NoTicketException.class)
	public JSONResult paySuccess(String orderId,String openId){
		TravelOrderVo order = travelOrderService.getOrderById(orderId);
		order.setPayStatus(1);
		//会生成验票的6位随机码返回给小程序
		String randomCode = MD5Utils.createRandomCode(6);
		order.setRandomCode(randomCode);
		order.setPayTime(new Date());
		order.setRealAmount(order.getOrderAmount());
		order.setPayAmount(order.getOrderAmount());
		travelOrderService.updateOrder(order);
		//分销记录
		JSONResult res = distrRecordService.getCommission(openId,order.getOrderAmount(),orderId);
		Map<String,Object> map = (Map<String, Object>) res.getData();
		List<DistrRecord> list = (List<DistrRecord>)map.get("recordList");
		DistrRecord record = list.get(0);
		CaseWithdra caseWithdra = new CaseWithdra();
		String id =UUID.randomUUID().toString().replace("-", "");
		caseWithdra.setId(id);
		caseWithdra.setCwdUserid(openId);
		caseWithdra.setCashAmout(record.getAmount());
		caseWithdra.setCreateTime(new Date());
		//插入提现增额表
		caseWithdraService.addCaseWithdra(caseWithdra);
		return JSONResult.ok("订单支付完成");
	}

	/**
	 * 订单支付完成回调更新订单状态
	 * @param request
	 * @param response
	 * @throws Exception
	 */
	 @RequestMapping("/wxNotify")
	 @ResponseBody
	 public void wxNotify(HttpServletRequest request,HttpServletResponse response) throws Exception
	 {
		 BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream()));
        String line = null;
        StringBuilder sb = new StringBuilder();
        while ((line = br.readLine()) != null) {
            sb.append(line);
        }
        br.close();
        //sb为微信返回的xml
        String notityXml = sb.toString();
        String resXml = "";

        Map map = PayUtil.doXMLParse(notityXml);

        String returnCode = (String) map.get("return_code");
        if ("SUCCESS".equals(returnCode)) {
            //验证签名是否正确
            Map<String, String> validParams = PayUtil.paraFilter(map);  //回调验签时需要去除sign和空值参数
            String prestr = PayUtil.createLinkString(validParams); 
            //根据微信官网的介绍，此处不仅对回调的参数进行验签，还需要对返回的金额与系统订单的金额进行比对等
            if (PayUtil.verify(prestr, (String) map.get("sign"), Constant.key, "utf-8")) {
                /**此处添加自己的业务逻辑代码start**/
                //更新订单状态
            	String orderId = (String) map.get("需要订单id");//TODO
            	TravelOrderVo order = travelOrderService.getOrderById(orderId);
            	order.setPayStatus(1);
            	//会生成验票的6位随机码返回给小程序
            	String randomCode = MD5Utils.createRandomCode(6);
            	order.setRandomCode(randomCode);
            	travelOrderService.updateOrder(order);
                /**此处添加自己的业务逻辑代码end**/
                //通知微信服务器已经支付成功
                resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
                        + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
            }
        } else {
            resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
                    + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
        }

        BufferedOutputStream out = new BufferedOutputStream(
                response.getOutputStream());
        out.write(resXml.getBytes());
        out.flush();
        out.close();
    }
	 
	 /**
	  * 获取订单详情
	  * @param orderId
	  * @return
	  */
	 @RequestMapping(value="/getOrderById", method = RequestMethod.POST)
	 public JSONResult getOrderById(String orderId)
	 {
		 TravelOrderVo order = travelOrderService.getOrderById(orderId);
		 return JSONResult.ok(order);
	 }
	 
	 /**
	  * 更新订单
	  * @param order
	  * @return
	  */
	 @RequestMapping("/updateOrder")
	 public JSONResult updateOrder(TravelOrder order)
	 {
		 travelOrderService.updateOrder(order);
		 return JSONResult.ok();
	 }
	 
	 /**
	  * 删除订单
	  * @param orderId
	  * @return
	  */
	 @PostMapping("/deleteOrder")
	 @ResponseBody
	 public JSONResult deleteOrder(String orderId)
	 {
		 travelOrderService.deleteOrder(orderId);
		 return JSONResult.ok();
	 }
	 /**
	  * 订单上添加人物
	  * @param orderId
	  */
	 @RequestMapping("/addUserOrder")
	 public JSONResult addUserInOrder(String orderId,@RequestBody List<OrderUser> orderUsers)
	 {
		 if(StringUtils.isEmpty(orderId))
		 {
			 return JSONResult.errorMsg("参数不全");
		 }
		 for (OrderUser orderUser : orderUsers) {
			 String id =UUID.randomUUID().toString().replace("-", "");
			 orderUser.setId(id);
			 orderUser.setOrderId(orderId);
		}
		 if(orderUsers.size() > 0)
		 {
			 orderUserService.batchAddOrderUser(orderUsers);
		 }
		 return JSONResult.ok(orderUsers);
	 }
	 /**
	  * 获取订单上的游客
	  * @param orderId
	  * @return
	  */
	 @RequestMapping("/getUserInfoInOrder")
	 public JSONResult getUserInfoInOrder(String orderId)
	 {
		 List<OrderUser> usersInOrder = orderUserService.getOrderUserByOrderId(orderId);
		 return JSONResult.ok(usersInOrder);
	 }
	 
	 /**
	  * 更新订单上的游客信息
	  * @param orderUser
	  * @return
	  */
	 @RequestMapping("/updateOrderUserInfo")
	 public JSONResult updateOrderUserInfo(OrderUser orderUser)
	 {
		 orderUserService.updateOrderUser(orderUser);
		 return JSONResult.ok();
	 }
	 
	 /**
	  * 获取订单上的顾客信息
	  * @param id
	  * @return
	  */
	 @RequestMapping("/getOrderUserInfo")
	 public JSONResult getOrderUserInfo(String id)
	 {
		 if(StringUtils.isEmpty(id))
		 {
			 return JSONResult.errorMsg("参数不全");
		 }
		 OrderUser orderUser = orderUserService.getOrderUserById(id);
		 return JSONResult.ok(orderUser);
	 }
	 
	 /**
	  * 获取订单分页信息
	  * @param reqMap reqMap中的key:goodsId线路/景点/酒店id;userId 下单人id;status 0未付款，1已付款/未出行，3已出行，4退款;
	  * @return
	  */
	 @RequestMapping(value="/queryOrderByPage", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
	 public JSONResult queryOrderByPage(@RequestBody(required = false) Map<String,Object> reqMap)
	 {
		 Integer page = (Integer) reqMap.get("page");
		 Integer pageSize = (Integer) reqMap.get("pageSize");
		 String userId = (String) reqMap.get("userId");
		 if(StringUtils.isEmpty(page)||StringUtils.isEmpty(pageSize)||StringUtils.isEmpty(userId))
		 {
			 return JSONResult.errorMsg("参数不全");
		 }
		 Page<TravelOrderVo> ipage = travelOrderService.queryOrderPage(page, pageSize,userId,reqMap);
			
		 return JSONResult.ok(ipage.getRecords());
	 }
	 
	/**
	 * 获取游客的订单分页数据
	 * @param reqMap page页码(必填);pageSize每页记录数(必填);userId:当前登陆人id（必填);
	 * payStatus:付款状态，0未支付，1已支付，2退款;tripStatus:出行状态，0未出行，1已出行
	 * @return
	 */
	 @RequestMapping(value="/queryOrderPageByUserId", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
	 public JSONResult queryOrderPageByUserId(@RequestBody Map<String,Object> reqMap)
	 {
		 Map<String,Object> map = (Map<String, Object>) reqMap.get("reqMap");
		 String pageNum = map.get("page").toString();
		 String pageSize = map.get("pageSize").toString();
		 String userId = map.get("userId").toString();
		 if(StringUtils.isEmpty(userId)||StringUtils.isEmpty(pageNum)||StringUtils.isEmpty(pageSize))
		 {
			 return JSONResult.errorMsg("参数不全");
		 }
		 Page<TravelOrderVo> ipage = travelOrderService.queryOrderPageByUserId(map);
		 return JSONResult.ok(ipage.getRecords());
	 }
	 /**
	  * 获取所有票的种类
	  * @return
	  */
	 @GetMapping("/getAllTicketType")
	 public JSONResult getAllTicketType()
	 {
		 List<TicketType> allTicketType = ticketTypeService.getAllTicketType();
		 return JSONResult.ok(allTicketType);
	 }
	 /**
	  * 获取指定日期内的订单数
	  * @param startDate 起始日期
	  * @param endDate 结束日期
	  *  @return innerLineReport:国内线路;outerLineReport:国外线路;scenicReport:景点;hotelReport:酒店;allReport:总计;xAxis:X轴
	 * @throws ParseException 
	  */
	 @PostMapping("/getOrderCountByDays")
	 public JSONResult getOrderCountByDays(String userId,Date startDate,Date endDate) throws ParseException
	 {
		 if(null == startDate || null == endDate || StringUtils.isEmpty(userId))
		 {
			 return JSONResult.errorMsg("参数不全");
		 }
		 Map<String,List<Object>> result = travelOrderService.getOrderCountByDays(userId,startDate,endDate);
		 return JSONResult.ok(result);
	 }
	 /**
	  * 获取指定月份的订单数，默认是当前月份
	  * @return totalOrder总订单数，usedOrder已使用订单数，unuserOrder未使用订单数，unverifyOrder待审核订单数，refundOrder退款订单数,
	  * lineCount线路数量,scenicCount景点数量,hotelCount酒店数量
	  */
	 @PostMapping("/getOrderNumByMonth")
	 public JSONResult getOrderNumByMonth(String userId,Date date)
	 {
		 if(StringUtils.isEmpty(userId))
		 {
			 return JSONResult.errorMsg("参数不全");
		 }
		 if(null == date)
		 {
			 date = new Date();
		 }
		 Map<String,Integer> result = travelOrderService.getOrderNumByMonth(userId,date);
		 return JSONResult.ok(result);
	 }
	 
	 

	/**
	 * 第一次审核
	 * @param travelOrder
	 * @return
	 */
	@PostMapping(value="/examFirst")
	public JSONResult examFirst(@RequestBody TravelOrderVo orderVo) {
		JSONResult result = null;
		try {
			travelOrderService.examFirst(orderVo);
			result = JSONResult.ok();
		} catch (Exception e) {
			e.printStackTrace();
			result = JSONResult.errorMsg(e.getMessage());
		}
		return result;
	}

	/**
	 * 订单第二次审核
	 * @param travelOrder
	 * @return
	 */
	@PostMapping(value="/examSecond")
	public JSONResult examSecond(TravelOrder travelOrder) {
		JSONResult result = null;
		try {
			travelOrderService.examSecond(travelOrder);
			result = JSONResult.ok();
		} catch (Exception e) {
			e.printStackTrace();
			result = JSONResult.errorMsg(e.getMessage());
		}
		return result;
	}
	
	/**
	 * 供应商验票
	 * @param supplyId 供应商id
	 * @param randomCode 客户端的随机码(客户支付订单后会返回这个随机码)
	 * @return
	 */
	@PostMapping("/checkOrder")
	public JSONResult checkOrder(String orderId)
	{
		if(StringUtils.isEmpty(orderId))
		{
			return JSONResult.errorMsg("参数不全");
		}
		boolean result = travelOrderService.checkOrder(orderId);
		if(result)
		{
			return JSONResult.ok("验票成功");
		}
		else
		{
			return JSONResult.errorMsg("验票失败，未获取到订单信息或供应商不符。");
		}
	}
	
	/**
	 * 搜索待验票的订单
	 * @param userId:登陆的用户id，必填项，checkCode:验票码或订单号，startDate:下单时间搜索的下限值，endDate:下单时间搜索的上限值
	 * @return
	 */
	@PostMapping("/searchCheckOrder")
	public JSONResult searchCheckOrder(@RequestBody(required = false) Map<String,Object> reqMap)
	{
		 String userId = (String) reqMap.get("userId");
		 if(StringUtils.isEmpty(userId))
		 {
			 return JSONResult.errorMsg("参数不全");
		 }
		  List<TravelOrderVo> orderVoList = travelOrderService.searchCheckOrder(reqMap);
			
		 return JSONResult.ok(orderVoList);
	 }
	
	/**
	  * 	获取待审核订单分页信息
	  * @param reqMap reqMap中的key:goodsId线路/景点/酒店id;userId 下单人id;status 0未付款，1已付款/未出行，3已出行，4退款;
	  * @return
	  */
	 @RequestMapping(value="/queryExamOrderByPage", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
	 public JSONResult queryExamOrderByPage(@RequestBody(required = false) Map<String,Object> reqMap)
	 {
		 Integer page = (Integer) reqMap.get("page");
		 Integer pageSize = (Integer) reqMap.get("pageSize");
		 String userId = (String) reqMap.get("userId");
		 if(StringUtils.isEmpty(page)||StringUtils.isEmpty(pageSize)||StringUtils.isEmpty(userId))
		 {
			 return JSONResult.errorMsg("参数不全");
		 }
		 Page<TravelOrderVo> ipage = travelOrderService.queryExamOrderByPage(page, pageSize,userId,reqMap);
			
		 return JSONResult.ok(ipage.getRecords());
	 }
	 
	 /**
	  * 财务管理获取订单分页数据
	  * @param reqMap
	  * @return
	  */
	 @PostMapping("/queryFinanceOrderByPage")
	 public JSONResult queryFinanceOrderByPage(@RequestBody(required = false) Map<String,Object> reqMap)
	 {
		 Integer page = (Integer) reqMap.get("page");
		 Integer pageSize = (Integer) reqMap.get("pageSize");
		 if(StringUtils.isEmpty(page)||StringUtils.isEmpty(pageSize))
		 {
			 return JSONResult.errorMsg("参数不全");
		 }
		 Page<TravelOrderVo> ipage = travelOrderService.queryFinanceOrderByPage(page, pageSize,reqMap);
			
		 return JSONResult.ok(ipage.getRecords());
	 }

}

